home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / g / gnu_c / pmlsrc23.zoo / pmltests / c2d.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-19  |  10.1 KB  |  422 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *                N O T I C E                *
  4.  *                                    *
  5.  *            Copyright Abandoned, 1987, Fred Fish        *
  6.  *                                    *
  7.  *    This previously copyrighted work has been placed into the    *
  8.  *    public domain by the author (Fred Fish) and may be freely used    *
  9.  *    for any purpose, private or commercial.  I would appreciate    *
  10.  *    it, as a courtesy, if this notice is left in all copies and    *
  11.  *    derivative works.  Thank you, and enjoy...            *
  12.  *                                    *
  13.  *    The author makes no warranty of any kind with respect to this    *
  14.  *    product and explicitly disclaims any implied warranties of    *
  15.  *    merchantability or fitness for any particular purpose.        *
  16.  *                                    *
  17.  ************************************************************************
  18.  */
  19.  
  20. /*
  21.  *  FILE
  22.  *
  23.  *    c2d.c   test complex to double math functions
  24.  *
  25.  *  KEY WORDS
  26.  *
  27.  *    portable math library
  28.  *    test functions
  29.  *
  30.  *  DESCRIPTION
  31.  *
  32.  *    Tests double precision functions for the Portable Math
  33.  *    Library.  Tests those functions which expect a single
  34.  *    double precision complex argument and return a double.
  35.  *
  36.  *    Most of the test data in the current data file (c2d.dat)
  37.  *    was generated using double precision FORTRAN arithmetic
  38.  *    on a Decsystem-20.
  39.  *
  40.  *    Note that the ordering of functions is important for
  41.  *    optimum error information.  Since some functions call
  42.  *    others in the library, the functions being called should
  43.  *    be tested first.  Naturally, an error in a lower level
  44.  *    function will cause propagation of errors up to higher
  45.  *    level functions.
  46.  *
  47.  *  USAGE
  48.  *
  49.  *    c2d [-esv] [-l limit]
  50.  *
  51.  *        -e    =>    force error for each test
  52.  *                to verify error handling
  53.  *
  54.  *        -l    =>    report errors greater than
  55.  *                specified limit (default 10**-6)
  56.  *
  57.  *        -s    =>    print summary after tests
  58.  *
  59.  *        -v    =>    print each function, argument,
  60.  *                and result
  61.  *
  62.  *    Test directives are read from the standard input, which
  63.  *    may be redirected to the provided test file (c2d.dat),
  64.  *    and any relative errors are automatically written to standard
  65.  *    output if they exceed a maximum allowable limit.
  66.  *    Each test directive has the form:
  67.  *
  68.  *        <name> <real(arg)> <imag(arg)> <expected result>
  69.  *
  70.  *    Each field is separated by a one or more space character(s).
  71.  *    The first field, "name", is the name of the function
  72.  *    to test. The second field is the real part of the argument.
  73.  *    The third field is the imaginary part of the argument.
  74.  *    The last field is the expected result.
  75.  *        
  76.  *  PROGRAMMER
  77.  *
  78.  *    Fred Fish
  79.  *    Tempe, Az 85281
  80.  *
  81.  */
  82.  
  83.  
  84. #include <stdio.h>
  85. #include <math.h>
  86.  
  87. #include "pml.h"
  88.  
  89. #ifdef atarist
  90. #define STDERR    stdout
  91. #else
  92. #define STDERR stderr
  93. #endif
  94.  
  95. #define MAX_ABS_ERR 1.0e-6    /* Set to catch only gross errors */
  96.  
  97. static int vflag;        /* Flag for verbose option */
  98. static int eflag;        /* Simulate an error to error printout */
  99. static int sflag;        /* Flag to show final statistics */
  100.  
  101. static double max_abs_err = MAX_ABS_ERR;
  102.  
  103. extern double cabs ();        /* Complex absolute value */
  104.  
  105.  
  106. /*
  107.  *    Define all recognized test functions.  Each function
  108.  *    must have an entry in this table, where each
  109.  *    entry contains the information specified in the 
  110.  *    structure "test".
  111.  *
  112.  */
  113.  
  114. struct test {            /* Structure of each function to be tested */
  115.     char *name;            /* Name of the function to test */
  116.     double (*func)();        /* Pointer to the function's entry point */
  117.     double max_err;        /* Error accumulator for this function */
  118. };
  119.  
  120. static struct test tests[] = {    /* Table of all recognized functions */
  121.     "cabs", cabs, 0.0,        /* Complex magnitude */
  122.     NULL, NULL, 0.0        /* Function list end marker */
  123. };
  124.  
  125.  
  126. /*
  127.  *  FUNCTION
  128.  *
  129.  *    main   entry point for c2d test utility
  130.  *
  131.  *  PSEUDO CODE
  132.  *
  133.  *    Begin main
  134.  *        Process any options in command line.
  135.  *        Do all tests requested by stdin directives.
  136.  *        Report final statistics (if enabled).
  137.  *    End main
  138.  *
  139.  */
  140.  
  141. main (argc, argv)
  142. int argc;
  143. char *argv[];
  144. {
  145.     ENTER ("main");
  146.     DEBUGWHO (argv[0]);
  147.     options (argc, argv);
  148.     dotests (argv);
  149.     statistics ();
  150.     LEAVE ();
  151. }
  152.  
  153.  
  154. /*
  155.  *  FUNCTION
  156.  *
  157.  *    dotests   process each test from stdin directives
  158.  *
  159.  *  ERROR REPORTING
  160.  *
  161.  *    Note that in most cases, the error criterion is based
  162.  *    on relative error, defined as:
  163.  *
  164.  *        error = (result - expected) / expected
  165.  *
  166.  *    Naturally, if the expected result is zero, some
  167.  *    other criterion must be used.  In this case, the
  168.  *    absolute error is used.  That is:
  169.  *
  170.  *        error = result
  171.  *
  172.  *  PSEUDO CODE
  173.  *
  174.  *    Begin dotests
  175.  *        While a test directive is successfully read from stdin
  176.  *        Default function name to "{null}"
  177.  *        Default real part of argument to 0.0
  178.  *        Default imaginary part of argument to 0.0
  179.  *        Default expected result to 0.0
  180.  *        Extract function name, argument and expected result
  181.  *        Lookup test in available test list
  182.  *        If no test was found then
  183.  *            Tell user that unknown function was specified
  184.  *        Else
  185.  *            Call function with argument and save result
  186.  *            If the verify flag is set then
  187.  *            Print function name, argument, and result
  188.  *            End if
  189.  *            If the expected result is not zero then
  190.  *            Compute the relative error
  191.  *            Else
  192.  *            Use the absolute error
  193.  *            End if
  194.  *            Get absolute value of error
  195.  *            If error exceeds limit or error force flag set
  196.  *            Print error notification on stderr
  197.  *            End if
  198.  *            If this error is max for given function then
  199.  *            Remember this error for summary
  200.  *            End if
  201.  *        End if
  202.  *        End while
  203.  *    End dotests
  204.  *
  205.  */
  206.  
  207.  
  208. dotests (argv)
  209. char *argv[];
  210. {
  211.     char buffer[256];        /* Directive buffer */
  212.     char function[64];        /* Specified function name */
  213.     COMPLEX argument;        /* Specified function argument */
  214.     double expected;        /* Specified expected result */
  215.     double result;        /* Actual result */
  216.     double error;        /* Relative or absolute error */
  217.     double abs_err;        /* Absolute value of error */
  218.     struct test *testp;        /* Pointer to function test */
  219.     struct test *lookup ();    /* Returns function test pointer */
  220.     register char *strp;    /* Pointer to next token in string */
  221.     extern char *strtok ();
  222.     extern double atof ();
  223.  
  224. #ifdef MJR
  225.     FILE * save_stdin, * re_stdin;
  226.     save_stdin = stdin;
  227.     re_stdin = freopen("c2d.dat","r",stdin);
  228.     if( re_stdin == (FILE *)NULL ) {
  229.     exit(-33);
  230.     }
  231. #endif
  232.     ENTER ("dotests");
  233.     while (fgets (buffer, sizeof(buffer), stdin) != NULL) {
  234.     strcpy (function, "{null}");
  235.     argument.real = 0.0;
  236.     argument.imag = 0.0;
  237.     expected = 0.0;
  238.     sscanf (buffer, "%s %le %le %le",
  239.     function, &argument.real, &argument.imag, &expected);
  240.         testp = lookup (function);
  241.         if (testp == NULL) {
  242.             fprintf (STDERR, "%s: unknown function \"%s\".\n",
  243.             argv[0], function);
  244.         } else {
  245.         result = (*testp -> func)(argument);
  246.         if (vflag) {
  247.             printf ("%s(%le + j %le) = %30.23le.\n",
  248.         function, argument.real, argument.imag, result);
  249.         }
  250.         if (expected != 0.0) {
  251.             error = (result - expected) / expected;
  252.         } else {
  253.             error = result;
  254.         }
  255.         if (error < 0.0) {
  256.         abs_err = -error;
  257.         } else {
  258.         abs_err = error;
  259.         }
  260.             if ((abs_err > max_abs_err) || eflag) {
  261.         fprintf (STDERR, "%s: error in \"%s\"\n", argv[0], function);
  262.         fprintf (STDERR, "\treal (arg)\t%25.20le\n", argument.real);
  263.         fprintf (STDERR, "\timag (arg)\t%25.20le\n", argument.imag);
  264.         fprintf (STDERR, "\tresult\t\t%25.20le\n", result);
  265.         fprintf (STDERR, "\texpected\t%25.20le\n", expected);
  266.             }
  267.         if (abs_err > testp -> max_err) {
  268.             testp -> max_err = abs_err;
  269.         }
  270.         }
  271.     }
  272. #ifdef MJR
  273.     fclose( re_stdin );
  274. #endif
  275.     LEAVE ();
  276. }
  277.  
  278.  
  279. /*
  280.  *  FUNCTION
  281.  *
  282.  *    options   process command line options
  283.  *
  284.  *  PSEUDO CODE
  285.  *
  286.  *    Begin options
  287.  *        Reset all flags to FALSE by default
  288.  *        Initialize flag argument scan pointer
  289.  *        If there is a second command line argument then
  290.  *        If the argument specifies flags then
  291.  *            While there is an unprocessed flag
  292.  *            Switch on flag
  293.  *            Case "force error flag":
  294.  *                Set the "force error" flag
  295.  *                Break switch
  296.  *            Case "print summary":
  297.  *                Set "print summary" flag
  298.  *                Break switch
  299.  *            Case "verbose":
  300.  *                Set "verbose" flag
  301.  *                Break switch
  302.  *            Default:
  303.  *                Tell user unknown flag
  304.  *                Break switch
  305.  *            End switch
  306.  *            End while
  307.  *        End if
  308.  *        End if
  309.  *    End options
  310.  *
  311.  */
  312.  
  313.  
  314. options (argc, argv)
  315. int argc;
  316. char *argv[];
  317. {
  318.     register int flag;
  319.     extern int getopt ();
  320.     extern char *optarg;
  321.  
  322.     ENTER ("options");
  323.     eflag = sflag = vflag = FALSE;
  324.     while ((flag = getopt (argc, argv, "#:el:sv")) != EOF) {
  325.     switch (flag) {
  326.         case '#':
  327.             DEBUGPUSH (optarg);
  328.         break;
  329.         case 'e':
  330.         eflag = TRUE;
  331.         break;
  332.         case 'l':
  333.             sscanf (optarg, "%le", &max_abs_err);
  334.         DEBUG3 ("args", "max_abs_err = %le", max_abs_err);
  335.         break;
  336.         case 's':
  337.         sflag = TRUE;
  338.         break;
  339.         case 'v':
  340.         vflag = TRUE;
  341.         break;
  342.     }
  343.     }
  344.     LEAVE ();
  345. }
  346.  
  347.  
  348. /*
  349.  *  FUNCTION
  350.  *
  351.  *    loopup   lookup test in known test list
  352.  *
  353.  *  DESCRIPTION
  354.  *
  355.  *    Given the name of a desired test, looks up the test
  356.  *    in the known test list and returns a pointer to the
  357.  *    test structure.
  358.  *
  359.  *    Since the table is so small we simply use a linear
  360.  *    search.
  361.  *
  362.  *  PSEUDO CODE
  363.  *
  364.  *    Begin lookup
  365.  *        For each known test
  366.  *        If the test's name matches the desired test name
  367.  *            Return pointer to the test structure
  368.  *        End if
  369.  *        End for
  370.  *    End lookup
  371.  *
  372.  */
  373.  
  374. struct test *lookup (funcname)
  375. char *funcname;
  376. {
  377.     struct test *testp;
  378.     struct test *rtnval;
  379.  
  380.     ENTER ("lookup");
  381.     rtnval = (struct test *) NULL;
  382.     for (testp = tests; testp -> name != NULL && rtnval == NULL; testp++) {
  383.     if (!strcmp (testp -> name, funcname)) {
  384.         rtnval = testp;
  385.      }
  386.     }
  387.     LEAVE ();
  388.     return (rtnval);
  389. }
  390.  
  391.  
  392. /*
  393.  *  FUNCTION
  394.  *
  395.  *    statistics   print final statistics if desired
  396.  *
  397.  *  PSEUDO CODE
  398.  *
  399.  *    Begin statistics
  400.  *        If a final statistics (summary) is desired then
  401.  *        For each test in the known test list
  402.  *            Print the maximum error encountered
  403.  *        End for
  404.  *        End if
  405.  *    End statistics
  406.  *
  407.  */
  408.  
  409. statistics ()
  410. {
  411.     struct test *tp;
  412.  
  413.     ENTER ("statistics");
  414.     if (sflag) {
  415.         for (tp = tests; tp -> name != NULL; tp++) {
  416.         printf ("%s:\tmaximum relative error %le\n", 
  417.             tp -> name, tp -> max_err);
  418.     }
  419.     }
  420.     LEAVE ();
  421. }
  422.